package com.atguigu.tingshu.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.util.MongoUtil;
import com.atguigu.tingshu.model.user.UserListenProcess;
import com.atguigu.tingshu.user.service.UserListenProcessService;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.atguigu.tingshu.vo.user.UserListenProcessVo;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@SuppressWarnings({"all"})
public class UserListenProcessServiceImpl implements UserListenProcessService {

	@Autowired
	private MongoTemplate mongoTemplate;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private RabbitService rabbitService;

	/**
	 * @author WeakMoon
	 * @date 2025/03/03 20:45:04
	 * 获取声音的上一次跳出时间
	 * 此方法用于根据用户ID和声音轨道ID获取用户在该声音轨道上的上一次监听中断时间
	 * 主要用于用户重新开始播放时，能够定位到上次中断的位置
	 *
	 * @param trackId 声音轨道ID，用于标识特定的声音轨道
	 * @param userId 用户ID，用于标识请求此信息的用户
	 * @return BigDecimal 返回用户上次离开该声音轨道的时间，单位为秒如果用户从未听过这个声音，则返回0
	 */
	@Override
	public BigDecimal getTrackBreakSecond(Long trackId,Long userId) {

	    // 创建查询条件，查找匹配指定声音轨道ID的文档
	    Query query = Query.query(Criteria.where("trackId").is(trackId));

	    // 获取用户监听进度的集合名称，基于用户ID和预定义的集合枚举
		String collectionName = this.getCollectionName(userId);

		// 使用MongoDB模板执行查询，尝试获取用户在指定声音轨道上的监听进度
	    UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);

	    // 如果找到了用户监听进度，则返回用户上次离开该声音轨道的时间
	    if (userListenProcess != null){
	        return userListenProcess.getBreakSecond();
	    }

	    // 如果没有找到用户监听进度，表示用户从未听过这个声音，返回0
	    return new BigDecimal("0");
	}

	private String getCollectionName(Long userId) {
		String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);
		return collectionName;
	}

	/**
	 * @author WeakMoon
	 * @date 2025/03/04 15:49:41
	 * 更新声音播放进度
	 */
	@Override
	public void updateListenProcess(UserListenProcessVo userListenProcessVo, Long userId) {
	    // 根据trackId构建查询条件
	    Query query = Query.query(Criteria.where("trackId").is(userListenProcessVo.getTrackId()));

	    // 获取用户对应的集合名称
	    String collectionName = this.getCollectionName(userId);

	    // 根据查询条件从MongoDB中查找用户声音播放进度记录
	    UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);

	    // 如果找到了用户的声音播放进度记录，则更新记录的播放中断时间点和更新时间
	    if (userListenProcess != null){
			// 更新修改时间
	        userListenProcess.setUpdateTime(new Date());
	        userListenProcess.setBreakSecond(userListenProcessVo.getBreakSecond());
	    }else {
	        // 如果没有找到用户的声音播放进度记录，则创建新的记录并设置相关属性
	        userListenProcess = new UserListenProcess();

			// 属性拷贝
	        BeanUtils.copyProperties(userListenProcessVo,userListenProcess);
	        userListenProcess.setUserId(userId);
	        userListenProcess.setCreateTime(new Date());
	        userListenProcess.setUpdateTime(new Date());
	    }
	    // 保存更新后的用户声音播放进度记录到MongoDB中
	    mongoTemplate.save(userListenProcess,collectionName);

		/**
		 * @author WeakMoon
		 * @date 2025/03/04 21:29:16
		 * 增加声音的播放量; 防止恶意刷新播放量
		 */

	    // 构建Redis键值，用于记录用户声音播放的状态
	    String key = "track:play:stat:" + userId + ":" + userListenProcessVo.getTrackId();

	    // 使用Redis的setIfAbsent方法，如果键不存在则设置键的值为"1"，并设置过期时间为1天
	    Boolean result = this.redisTemplate.opsForValue().setIfAbsent(key, "1", 1, TimeUnit.DAYS);

	    // 如果Redis键设置成功，表示用户开始播放新的声音，发送消息到RabbitMQ，用于统计声音播放次数
	    if (result){
			// 执行成功 说明第一次播放
	        TrackStatMqVo trackStatMqVo = new TrackStatMqVo();
	        trackStatMqVo.setTrackId(userListenProcessVo.getTrackId());
	        trackStatMqVo.setAlbumId(userListenProcessVo.getAlbumId());
	        trackStatMqVo.setStatType(SystemConstant.TRACK_STAT_PLAY);
	        trackStatMqVo.setCount(1);
	        // 生成唯一的业务编号，防止消息重复消费
	        String businessNo = UUID.randomUUID().toString().replaceAll("_","");
	        trackStatMqVo.setBusinessNo(businessNo);
	        // 发送消息到RabbitMQ
	        this.rabbitService.sendMessage(MqConst.EXCHANGE_TRACK,MqConst.ROUTING_TRACK_STAT_UPDATE, JSON.toJSONString(trackStatMqVo));
	    }
	}

	/**
	 * @author WeakMoon
	 * @date 2025/03/05 16:52:26
	 * 获取最近一次播放声音
	 */
	@Override
	public Map<String, Object> getLatelyTrack(Long userId) {
	    // 创建一个map 集合
	    Map<String, Object> map = new HashMap<>();

	    // 查询MongoDB;
	    String collectionName = this.getCollectionName(userId);

	    Query query = new Query();
	    // 使用降序排序查询，限制结果数量为1，以获取最近更新的记录
	    query.with(Sort.by(Sort.Direction.DESC, "updateTime")).limit(1);

	    // 执行查询，获取最近一次播放的音轨信息
	    List<UserListenProcess> userListenProcessList = this.mongoTemplate.find(query, UserListenProcess.class, collectionName);
	    UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);

		// 打印音轨ID和专辑ID
	    System.out.println(userListenProcess.getTrackId()+":\t"+userListenProcess.getAlbumId());

	    // 存储数据
	    // 将最近一次播放的音轨ID和专辑ID存入map中
	    map.put("trackId",userListenProcessList.get(0).getTrackId());
	    map.put("albumId",userListenProcessList.get(0).getAlbumId());

	    // 返回存储音轨信息的map
	    return map;
	}
}
